import { useState, useRef, useCallback, useEffect, useMemo } from 'react'
import { useRouter } from 'next/router'
import Image from 'next/image'
import Head from 'next/head'
import {
  Textarea,
  Input,
  Select,
  SelectItem,
  Button,
  Tooltip,
  Modal,
  ModalContent,
  ModalBody,
} from '@nextui-org/react'
import { Inter } from 'next/font/google'
import Title from '@/components/Title'
import Hero from '@/components/Hero'
import Steps from '@/components/Steps'
import Intro from '@/components/Intro'
import Entries from '@/components/Entries'
import FAQ from '@/components/FAQ'
import Output from '@/components/Output'

import { useGlobalContext } from '@/contexts'
import initAssistantRequest from '@/shared/assistantRequest'
import { getPageData, getCreateParams, getSelectOptions } from '@/shared/utils'
import { AssistantProps } from '~/src/services'

import iconMagic from '@/assets/icons/ic_magic.png'
import runoutPC from '@/assets/runout-pc.png'
import runoutMobile from '@/assets/runout-mobile.png'

const inter = Inter({ subsets: ['latin'] })

const Generator = () => {
  const router = useRouter()
  const { pathname } = router
  const { insData } = useGlobalContext()
  const [keywords, setKeywords] = useState('')
  const [category, setCategory] = useState('')
  const [accountType, setAccountType] = useState('')
  const [nameStyle, setNameStyle] = useState('')

  const [modalOpen, setModalOpen] = useState(false)
  const [isLoading, setIsLoading] = useState(false)
  const [errorTips, setErrorTips] = useState('')
  const [errorTipsOpen, setErrorTipsOpen] = useState(false)
  const [replyData, setReplyData] = useState('')
  const [historyList, setHistoryList] = useState<
    { timestamp: number; value: string }[]
  >([])

  const abortController = useRef<AbortController>()
  const textRef = useRef('')
  const timestampRef = useRef(0)

  const pageData = useMemo(
    () => getPageData(pathname, insData) as AssistantProps,
    [pathname, insData]
  )

  const categoryData = useMemo(() => {
    const code = 'Category'
    return getSelectOptions(pageData, code)
  }, [pageData])

  const accountData = useMemo(() => {
    const code = 'Account Type'
    return getSelectOptions(pageData, code)
  }, [pageData])

  const nameStyleData = useMemo(() => {
    const code = 'Name Style'
    return getSelectOptions(pageData, code)
  }, [pageData])

  useEffect(() => {
    if (!category && categoryData?.length) {
      setCategory(categoryData[0].value)
    }
  }, [category, categoryData?.length])

  useEffect(() => {
    if (!accountType && accountData?.length) {
      setAccountType(accountData[0].value)
    }
  }, [accountType, accountData?.length])

  useEffect(() => {
    if (!nameStyle && nameStyleData?.length) {
      setNameStyle(nameStyleData[0].value)
    }
  }, [nameStyle, nameStyleData?.length])

  useEffect(() => {
    setTimeout(() => setErrorTipsOpen(false), 1000 * 5)
  }, [errorTips])

  const handleMessagesStream = useCallback((stream: string) => {
    if (!stream) return

    if (!textRef.current) {
      timestampRef.current = new Date().getTime()
    }

    textRef.current += stream.replace(/(\n|-=- --)/g, ' ')
    textRef.current = textRef.current.replace(/(\n|-=-n--)/g, '<br/>')

    setReplyData(textRef.current)
  }, [])

  const errorHandler = useCallback((type: string, failedType: string) => {
    // trackAssistant('error', { status: type, failedType })
    setErrorTips(failedType)
    setErrorTipsOpen(true)
  }, [])

  const handleOpenError = useCallback(
    (status: string) => {
      setIsLoading(false)

      const maps: { [key: string]: () => void } = {
        '202': () => {
          errorHandler('202', 'validate failed')
        },
        '241': () => {
          // credit run out
          // errorHandler('241', 'credit run out')
          setModalOpen(true)
        },
        '277': () => {
          errorHandler('277', 'request too much')
        },
        '278': () => {
          errorHandler('278', 'request frequency has reached the upper limit')
        },
        '279': () => errorHandler('279', 'forbidden words'),
        '280': () => {
          errorHandler(
            '280',
            'The input context exceeds 2000 characters, please cut it down and try again.'
          )
        },
        '401': () => {
          // free credit run out
          // errorHandler('401', 'free credit run out')
          setModalOpen(true)
        },
        '403': () => {
          // forbidden words
          errorHandler(
            '403',
            'There is a risk of violations, which may be due to factors such as violations and pornography'
          )
        },
        '429': () => {
          errorHandler('429', 'request frequency has reached the upper limit')
        },
      }
      if (maps[status]) {
        maps[status]()
        return
      } else {
        errorHandler(`${status}`, 'Server Error')
      }
    },
    [errorHandler]
  )

  const handleResetAnswerState = () => {
    textRef.current = ''
    timestampRef.current = 0
  }

  const handleMessageEnd = () => {
    setReplyData('')
    setHistoryList((prev) => [
      { timestamp: timestampRef.current, value: textRef.current },
      ...prev,
    ])
  }

  const handleGenerate = () => {
    if (!pageData) return
    const { assistantRequest, abortController: controller } =
      initAssistantRequest()

    abortController.current = controller

    setIsLoading(true)

    const createPrams = getCreateParams(pageData, [
      keywords,
      category,
      accountType,
      nameStyle,
    ])

    assistantRequest({
      data: createPrams,
      language: 'en',
      onOpenSuccess(response: any) {
        console.log('onOpenSuccess event >>>', response)
        handleResetAnswerState()
        if (response.status !== 200) {
          handleOpenError(response.status)
        }
      },
      onOpenError: (response: any) => {
        console.log('onOpenError event >>>', response)
        handleOpenError(response.status)
      },
      onMessage: (event: any) => {
        handleMessagesStream(event?.data)
      },
      onMessageEnd: () => {
        console.log('onMessageEnd event >>>')
        handleMessageEnd()
        // handleMessageStreamEnd()
      },
      onClose: () => {
        console.log('onClose event >>>')
        setIsLoading(false)
      },
      onError: (event: any) => {
        console.log('onError event >>>', event)
        setIsLoading(false)
      },
    }).catch((err) => {
      console.log('assistantRequest err >>>>', err)
    })
  }

  return (
    <>
      <div className="flex flex-col gap-y-4 w-[840px] min-h-[316px] px-3.5 py-6 bg-white mx-[auto] mb-row shadow-lg max-sm:w-full max-sm:mb-0 rounded-[20px]">
        <div className="flex flex-col gap-y-2">
          <div className="flex flex-row items-center justify-between">
            <span className="text-base font-bold">Short Description *</span>
            <span className="text-sm text-secondary">
              {keywords.length}/200
            </span>
          </div>
          <Textarea
            variant="bordered"
            placeholder="Enter name ideas or keywords"
            value={keywords}
            onValueChange={(val) => {
              setKeywords(val.slice(0, 200))
            }}
          />
        </div>
        <div className="flex flex-col gap-y-2">
          <div className="flex flex-row items-center justify-between">
            <span className="text-base font-bold">Category</span>
          </div>
          {categoryData && (
            <Select
              aria-label="select language"
              variant="bordered"
              selectionMode="single"
              items={categoryData}
              selectedKeys={[category]}
              defaultSelectedKeys={[category]}
              onSelectionChange={(val: any) => {
                setCategory(val.currentKey)
              }}
            >
              {categoryData.map((item) => (
                <SelectItem key={item.value} value={item.value}>
                  {item.label}
                </SelectItem>
              ))}
            </Select>
          )}
        </div>
        <div className="flex flex-row justify-between gap-x-8 max-sm:flex-col max-sm:gap-y-4">
          <div className="flex-1 flex flex-col gap-y-2">
            <div className="flex flex-row items-center justify-between">
              <span className="text-base font-bold">Account Type</span>
            </div>
            {accountData && (
              <Select
                aria-label="select language"
                variant="bordered"
                selectionMode="single"
                items={accountData}
                selectedKeys={[accountType]}
                defaultSelectedKeys={[accountType]}
                onSelectionChange={(val: any) => {
                  setAccountType(val.currentKey)
                }}
              >
                {accountData.map((item) => (
                  <SelectItem key={item.value} value={item.value}>
                    {item.label}
                  </SelectItem>
                ))}
              </Select>
            )}
          </div>
          <div className="flex-1 flex flex-col gap-y-2">
            <div className="flex flex-row items-center justify-between">
              <span className="text-base font-bold">Name Style</span>
            </div>
            {nameStyleData && (
              <Select
                aria-label="select language"
                variant="bordered"
                selectionMode="single"
                items={nameStyleData}
                selectedKeys={[nameStyle]}
                onSelectionChange={(val: any) => {
                  setNameStyle(val.currentKey)
                }}
              >
                {nameStyleData.map((item) => (
                  <SelectItem key={item.value} value={item.value}>
                    {item.label}
                  </SelectItem>
                ))}
              </Select>
            )}
          </div>
        </div>
        <Tooltip
          color={'danger'}
          isOpen={errorTipsOpen}
          showArrow
          isDismissable
          placement="bottom"
          content={errorTips}
        >
          <Button
            className="flex w-full button-primary cursor-pointer"
            isDisabled={!keywords.length || isLoading}
            isLoading={isLoading}
            onClick={handleGenerate}
          >
            <Image src={iconMagic} alt="icon" width={22} height={22} />
            Generate
          </Button>
        </Tooltip>
        <div className="flex flex-col gap-4 max-sm:hidden">
          {[
            { timestamp: timestampRef.current, value: replyData },
            ...historyList,
          ].map((item, index) => (
            <Output
              key={`${item.timestamp}-${index}`}
              timeStamp={new Date().getTime()}
              content={item.value}
              // onCopy={() => {}}
              onDelete={() => setHistoryList((prev) => prev.splice(index, 1))}
            />
          ))}
        </div>
      </div>
      <div className="flex flex-col gap-6 pt-6 lg:hidden">
        {[
          { timestamp: timestampRef.current, value: replyData },
          ...historyList,
        ].map((item, index) => (
          <Output
            key={`${item.timestamp}-${index}`}
            timeStamp={new Date().getTime()}
            content={item.value}
            // onCopy={() => {}}
            onDelete={() => setHistoryList((prev) => prev.splice(index, 1))}
          />
        ))}
      </div>
      <Modal
        isOpen={modalOpen}
        placement="center"
        onClose={() => setModalOpen(false)}
      >
        <ModalContent>
          <ModalBody className="p-0">
            <Image
              className="max-sm:hidden"
              src={runoutPC}
              alt="run out picture"
              width={819}
              height={662}
            ></Image>
            <Image
              className="sm:hidden"
              src={runoutMobile}
              alt="run out picture"
              width={640}
              height={872}
            ></Image>
          </ModalBody>
        </ModalContent>
      </Modal>
    </>
  )
}

export default function Home() {
  const HeroData = {
    title: 'Use AI to Generate Instagram User Name Ideas',
    desc: [
      `In the digital age, platforms like Instagram are crucial for building connections, building your brand, and expanding your audience. To stand out in the crowd and make a lasting impression, you will need a unique and memorable username. That's why we bring you the free tool - Instagram username generator powered by AI.`,
      `Our tool is designed to provide creative and unique username suggestions for your Instagram account. Just enter a few keywords that describe your brand or interests, and the AI will quickly generate a list of username options. It considers factors like popularity, uniqueness, and length to ensure the usernames are both appealing and practical.`,
    ],
    img: require('@/assets/username/hero.png').default,
  }
  const StepsData = {
    title: 'How to Use the Instagram Name Generator？',
    desc: `Having trouble finding a catchy and memorable username for Instagram? Let our Instagram username generator do the work for you. It effortlessly generates aesthetic and unique Instagram user name ideas in just five seconds. Plus, it's super easy to use!`,
    steps: [
      {
        step: 'Step 1',
        title: 'Provide Instagram account name ideas',
        desc: 'Begin by entering a few words that describe you or your business, select the type of account you have (personal or business), and choose the category that best fits your brand or interests. This information helps the AI generate a name that perfectly aligns with your brand identity or personal style.',
        img: require('@/assets/username/step-1.png').default,
      },
      {
        step: 'Step 2',
        title: 'Generate Instagram username',
        desc: `After inputting all the necessary information, click the 'Generate' button. The Instagram username maker will use the details you've provided to generate a list of usernames. These usernames are usually creatively designed and relevant to the keywords and categories you specify.`,
        img: require('@/assets/username/step-2.png').default,
      },
      {
        step: 'Step 3',
        title: 'Select and apply',
        desc: `Review the generated usernames and pick the one that most closely reflects your brand or personal style. Once you've made your choice, go ahead and register this new username on Instagram, provided it is available. If your preferred username is already taken, you can use the Instagram name generator again, adjust your input, or try new keywords to find available names.`,
        img: require('@/assets/username/step-3.png').default,
      },
    ],
  }
  const IntroData = {
    title: 'How to Choose the Perfect Name for Instagram?',
    desc: `While an Instagram username may seem like a small decision, choosing the right one can instantly build your brand identity and discoverability. On Instagram, a good, unique username is crucial for making a memorable first impression, helping people discover you through search, and ensuring they remember you. Here are some tips to help you choose from AI-generated Instagram username ideas to ensure your username stands out.`,
    intros: [
      {
        title: 'Simple and memorable',
        desc: `Choose a username that's easy to remember and hard to misspell. This makes it more likely that people will find your profile when they search for you.`,
        img: require('@/assets/username/icon-like.png'),
      },
      {
        title: 'Unique and relevant',
        desc: `Your username should reflect your brand or personal identity. Get creative with wordplay to make it stand out, such as including your name or relevant niche keywords.`,
        img: require('@/assets/username/icon-followers.png'),
      },
      {
        title: 'Check availability',
        desc: `Before settling on an Instagram username, check to see if the username is available on other social media platforms. Using the same username across platforms makes it easier for your audience to find and follow you.`,
        img: require('@/assets/username/icon-check.png'),
      },
      {
        title: 'Plan for the future',
        desc: `Choose a username that gives you room to grow. Avoid names that are too specific, as they may not fit if you expand your brand or change direction.`,
        img: require('@/assets/username/icon-versatility.png'),
      },
      {
        title: 'Avoid complex characters',
        desc: `Avoid using usernames with numbers, underscores, or special symbols, as these can confuse potential followers and make your username harder to find and remember.`,
        img: require('@/assets/username/icon-thunmup.png'),
      },
    ],
  }
  const EntriesData = {
    title: 'Dicover More Instagram Generator Tools',
    entries: [
      {
        label: 'Instagram Hashtag Generator',
        link: '/instagram-hashtag-generator/',
      },
      {
        label: 'Instagram Caption Generator',
        link: '/instagram-caption-generator/',
      },
      { label: 'Instagram Bio Generator', link: '/instagram-bio-generator/' },
    ],
  }
  const FAQData = {
    title: 'FAQs',
    faqs: [
      {
        question: 'How long is an Instagram username?',
        answer: 'The maximum length of an Instagram username is 30 characters.',
      },
      {
        question: 'How to make AI generate random Instagram username?',
        answer:
          'To generate random Instagram username using SSSgram, just choose Random from the given styles.',
      },
      {
        question: 'Can you change your Instagram username more than 2 times?',
        answer:
          'Yes, you can change your Instagram username more than twice. Instagram does not have a specific limit on how many times you can change your username.',
      },
    ],
  }
  return (
    <main
      className={`w-view min-h-screen mx-[auto] ${inter.className} max-sm:w-sView max-sm:px-[10px]`}
    >
      <Head>
        <title>
          100% Free AI Instagram Name Generator: Random & Cool Name Ideas
        </title>
        <meta
          name="description"
          content="Generate unique, cool or cute Instagram name ideas with the AI-powered Instagram username generator in seconds. Save time and effort."
        />
        <meta
          property="og:title"
          content="100% Free AI Instagram Name Generator: Random & Cool Name Ideas"
        />
        <meta
          property="og:description"
          content="Generate unique, cool or cute Instagram name ideas with the AI-powered Instagram username generator in seconds. Save time and effort."
        />
      </Head>
      <Title
        title="Free AI Instagram Name Generator"
        desc="Come up with unique, cool or cute Instagram name ideas with the Instagram username generator free online."
      ></Title>
      <Generator />
      <Hero {...HeroData} />
      <Steps {...StepsData} />
      <Intro {...IntroData} />
      <FAQ {...FAQData} />
      <Entries {...EntriesData} />
    </main>
  )
}
